﻿using System;
using System.Collections.Generic;
using System.Text;
using lin;

/// <summary>
/// 游戏包间
/// </summary>
public class Room
{
    public const int MAX_USER_COUNT = 1;//房间最大人数
    public const int MAX_PAI_NUM = 54;//单幅牌数量
    public const int UNITE_SCORE = 3;//单局分值

    public int id;
    public UserToken[] users = new UserToken[MAX_USER_COUNT];
    public List<string> paiList = new List<string>();
    Random rand = new Random();
    int landlordId;//地主seatId
    private int curSeatId;

    public Room(int roomId)
    {
        id = roomId;
    }

    //用户进入房间
    public void AddUser(UserToken token)
    {
        int index = GetEmptyIndex();
        token.user.seatId = index;
        token.user.roomId = this.id;

        users[index] = token;

        //匹配成功，返回匹配消息
        RspMatch rsp = new RspMatch();
        rsp.roomId = id;
        rsp.seatId = index;
        for (int i = 0; i < users.Length; i++)
        {
            if(users[i]!=null)
            {
                rsp.users.Add(users[i].user);
            }
        }
        //发送给当前用户，房间内所有人
        Server.Send(token, Protocol.ReqMatch, rsp);

        //发送给其他人，当前用户进入游戏
        BroadRoom(Protocol.RspOtherJoin,token.user,token);
    }

    //获取一个空的座位号
    int GetEmptyIndex()
    {
        for (int i = 0; i < MAX_USER_COUNT; i++)
        {
            if (users[i] == null)
            {
                return i;
            }
        }
        return -1;
    }
    
    //是否有空位
    public bool HasSeat()
    {
        return GetEmptyIndex() != -1;
    }

    public void SetReady(UserToken token)
    {
        token.user.isReady = true;

        //广播用户准备
        RspReady rsp = new RspReady();
        rsp.seatId = token.user.seatId;
        BroadRoom(Protocol.ReqReady, rsp);

        CheckReadyFinish();
    }


    void CheckReadyFinish()
    {
        //检测玩家全部准备
        if (ReadyCount() == MAX_USER_COUNT)
        {
            Console.WriteLine("房间：{0}，开始游戏", id);
            StartGame();
        }
    }
    //房间准备玩家数量
    int ReadyCount()
    {
        int count = 0;
        for (int i = 0; i < users.Length; i++)
        {
            if(users[i]!=null && users[i].user.isReady)
            {
                count++;
            }
        }
        return count;
    }

    //开始游戏
    void StartGame()
    {
        //洗牌
        WashPai();

        //随机叫地主的人
        curSeatId = 0;//rand.Next(0, users.Length);

        RspSeatId rob = new RspSeatId();
        rob.seatId = curSeatId;

        //分别给玩家发送不一样的手牌
        for (int i = 0; i < MAX_USER_COUNT; i++)
        {
            RspSendPai rsp = new RspSendPai();
            List<string> pais = GetOnePai();
            rsp.pais.AddRange(pais);
            //添加玩家手牌缓存
            users[i].user.pais.AddRange(pais);

            //发牌
            Server.Send(users[i], Protocol.RspSendPais, rsp);
            //抢地主回合
            Server.Send(users[i], Protocol.RspRobTurn, rob);
            Console.WriteLine(rob);
            Console.WriteLine(rob.seatId);
            
        }
    }

    //洗牌
    void WashPai()
    {
        paiList.Clear();
        for (int i = 1; i <= 13; i++)
        {
            for (int j = 1; j <= 4; j++)
            {
                paiList.Add(j + "_" + i);
            }
        }
        paiList.Add("5_17");
        paiList.Add("5_18");
    }

    //获得一手牌 17张随机的牌
    List<string> GetOnePai()
    {
        List<string> pais = new List<string>();
        for (int i = 0; i < 17; i++)
        {
            int index = rand.Next(0,paiList.Count);
            pais.Add(paiList[index]);
            //移除牌
            paiList.RemoveAt(index);
        }
        return pais;
    }

    //抢地主
    public void RobLandlord(UserToken token)
    {
        token.user.isLandlord = true;
        landlordId = token.user.seatId;

        //广播地主
        ReqPais rsp = new ReqPais();
        rsp.seatId = token.user.seatId;
        Console.WriteLine(rsp.pais.Count);
        for (int i = 0; i < 3; i++)
        {
            rsp.pais.Add(paiList[i]);
            //添加地主牌缓存
            token.user.pais.Add(paiList[i]);
        }
        paiList.Clear();
        Console.WriteLine(rsp.pais.Count);
        BroadRoom(Protocol.RspLandlord, rsp);
    }

    //不抢
    public void NotRobLandlord(UserToken token)
    {
        //广播不抢
        RspSeatId rsp = new RspSeatId();
        rsp.seatId = curSeatId;
        BroadRoom(Protocol.ReqNotRob, rsp);


        //下一个开始抢
        curSeatId++;
        if(curSeatId >= users.Length)
        {
            curSeatId = 0;
        }
        RspSeatId rob = new RspSeatId();
        rob.seatId = curSeatId;
        BroadRoom(Protocol.RspRobTurn, rob);
    }

    //玩家出牌
    public void PutCard(ReqPais req)
    {
        Console.WriteLine("出牌：" + req.seatId);
        BroadRoom(Protocol.ReqPutCard, req);

        //删除打出的牌
        users[req.seatId].user.round++;
        for (int i = 0; i < req.pais.Count; i++)
        {
            users[req.seatId].user.pais.Remove(req.pais[i]);
        }

        //检测游戏结束
        int result = CheckGameOver();
        if (result>-1)
        {
            GameOver(result);
        }
        else
        {
            NextPutTurn();
        }
    }

    //下个人出牌回合++
    void NextPutTurn()
    {
        curSeatId++;
        if (curSeatId >= users.Length)
        {
            curSeatId = 0;
        }

        //广播所有人，出牌回合
        RspSeatId rob = new RspSeatId();
        rob.seatId = curSeatId;

        BroadRoom(Protocol.RspPutTurn, rob);
    }

    //玩家要不起
    public void PassPutCard(UserToken token)
    {
        //广播要不起
        RspSeatId rsp = new RspSeatId();
        rsp.seatId = rsp.seatId;

        BroadRoom(Protocol.ReqPassCard,rsp);

        NextPutTurn();
    }

    //检测游戏结束
    int CheckGameOver()
    {
        for (int i = 0; i < users.Length; i++)
        {
            if(users[i].user.pais.Count==0)
            {
                return i;
            }
        }
        return -1;
    }

    //游戏结算
    void GameOver(int win)
    {
        RspGameOver rsp = new RspGameOver();
        rsp.winSeatId = win;
        rsp.winType = CheckSpring(win) ? 1 : 0;
        rsp.landlordId = landlordId;

        for (int i = 0; i < users.Length; i++)
        {
            //分别结算每个人的信息
            Result rs = new Result();
            rs.seatId = i;
            rs.username = users[i].user.username;
            rs.addScore = WinScore(i, win);
            users[i].user.score += rs.addScore;
            rs.score = users[i].user.score;
            rs.pais.AddRange(users[i].user.pais);

            rsp.results.Add(rs);
        }

        BroadRoom(Protocol.RspGameOver, rsp);


        //清空数据
        for (int i = 0; i < users.Length; i++)
        {
            users[i].user.isReady = false;
            users[i].user.isLandlord= false;
            users[i].user.round= 0;
            users[i].user.pais.Clear();
        }
    }

    //重新开始
    public void Restart(UserToken token)
    {
        token.user.isReady = true;

        //广播用户准备
        RspReady rsp = new RspReady();
        rsp.seatId = token.user.seatId;
        BroadRoom(Protocol.ReqRestart, rsp);

        CheckReadyFinish();
    }

    //计算赢得分数
    int WinScore(int seatId,int winId)
    {
        if(seatId==winId)
        {
            if (landlordId == seatId)
            {
                return UNITE_SCORE * 2;
            }
            else
            {
                return UNITE_SCORE;
            }
        }
        else
        {
            if (landlordId == seatId)
            {
                return -UNITE_SCORE * 2;
            }
            else
            {
                return -UNITE_SCORE;
            }
        }
    }

    //检测是否春天
    bool CheckSpring(int win)
    {
        //地主赢
        if(users[win].user.isLandlord)
        {
            for (int i = 0; i < users.Length; i++)
            {
                if(i!=win && users[i].user.pais.Count<17)
                {
                    return false;
                }
            }
            return true;
        }
        //农民赢
        else
        {
            return users[landlordId].user.round < 2;
        }
    }

    //玩家离线
    public void Offline(UserToken token)
    {
        for (int i = 0; i < users.Length; i++)
        {
            if(users[i]==token)
            {
                users[i] = null;
                break;
            }
        }
        //广播离线
        BroadRoom(Protocol.Offline, token.user);
    }

    //房间广播其他人
    public void BroadRoom<T>(Protocol pbId,T t, UserToken except)
    {
        for (int i = 0; i < users.Length; i++)
        {
            if (users[i] != null && users[i] != except)
            {
                Server.Send(users[i], pbId, t);
            }
        }
    }

    //房间广播所有人
    public void BroadRoom<T>(Protocol pbId, T t)
    {
        for (int i = 0; i < users.Length; i++)
        {
            if (users[i] != null)
            {
                Server.Send(users[i], pbId, t);
            }
        }
    }
}

